#ifndef __cp15_h__
#define __cp15_h__
#include "types.h"
//The System Control coprocessor can contain up to 16 primary registers, 
//each of which is 32 bits long.

//0 ID codes (read-only) Processor ID, Cache,Tightly-coupled Memory and TLB type
//Register 0: ID codes on page B3-7


//Table B3-2 System Control coprocessor ID registers
// opcode2
//0b000 Main ID register Main ID register
//0b001 Cache type register Cache type register on page B3-10
//0b010 Tightly Coupled Memory (TCM) type register TCM type register on page B3-10
//0b011 TLB type register
//0b100 MPU type register (PMSAv6)
typedef enum System_Control_coprocessor_ID_registers{
	MainId,
	CacheType,
	TCMType,
	TLBType,
	MPUType,
	Other
} ID_REG;

typedef struct _cp15_reg_ARM7processorID{
	__u32 Revision:4;
	__u32 Primary_part_number:12;
	__u32 Variant:7;
	__u32 A:1;
	__u32 Implementor:8;
} ARM7PROCESSORID;
//Bits[31:24] of the main ID register contain an implementor code.
//The following codes are defined (all other values of the architecture code are reserved by ARM Limited.):
//0x41 A (ARM Limited)
//0x44 D (Digital Equipment Corporation)
//0x4D M (Motorola - Freescale Semiconductor Inc.)
//0x56 V (Marvell Semiconduct
//0x69 i (Intel Corporation)
#define ArmImpentor_Arm  'A'
#define ArmImpentor_Dec  'D'
#define ArmImpentor_Moto 'M'
#define ArmImpentor_Marvell 'V'
#define ArmImpentor_Intel   'i'

typedef struct _cp15_reg_postARM7processorID{
	__u32 Revision:4;
	__u32 Primary_part_number:12;
	__u32 Architecture:4;
	__u32 Variant:4;
	__u32 mplementor:8;
} POSTARM7PROCESSORID;


//Bits[19:16] Contain an architecture code. The following architecture codes are defined:
//0x1 ARM architecture v4
//0x2 ARM architecture v4T
//0x3 ARM architecture v5
//0x4 ARM architecture v5T
//0x5 ARM architecture v5TE
//0x6 ARM architecture v5TEJ
//0x7 ARM architecture v6
//0xF Revised CPUID format. Details available from ARM.
typedef union main_id_register
{
	ARM7PROCESSORID arm7;
	POSTARM7PROCESSORID arm7p;

}MainIdReg;
#define  ARMarchitecturev4     1
#define  ARMarchitecturev4T    2
#define  ARMarchitecturev5     3
#define  ARMarchitecturev5T    4
#define  ARMarchitecturev5TE   5
#define  ARMarchitecturev5TEJ  6
#define  ARMarchitecturev6     7

typedef struct _cp15_reg_CacheTypeRegister{
	__u32 Isize:12;
	__u32 Dsize:12;
	__u32 S:1;
	__u32 ctype:4;
	__u32 c_32:3;	// should be 000
} CacheTypeReg;
typedef struct _cp15_reg_TCMTypeRegister{
	__u32 ITCM:3;
	__u32 c_18:13;	// should be 0000000000000
	__u32 DTCM:3;
	__u32 c_29:8;	// should be 00000000
	__u32 c_32:3;	// should be 000
} TCMTypeReg;
typedef struct _cp15_reg_TLBTypeRegister{
	__u32 S:1;
	__u32 c_8:7;	// should be 0000000
	__u32 DLsize:8;
	__u32 ILsize:8;
	__u32 c_32:8;	// should be 00000000
} TLBTypeReg;
typedef struct _cp15_reg_MPUTypeRegister{
	__u32 S:1;
	__u32 c_8:7;	// should be 0000000
	__u32 DRegion:8;
	__u32 IRegion:8;
	__u32 c_32:8;	// should be 00000000
} MPUTypeReg;






//1 Control bits (read/write) System Configuration Bits 
//Control register on page B3-12, and Register 1: Control register on page B4-40

//Table B3-3 System Control coprocessor Control registers
//opcode2 Register
//0b000 Control register
//0b001 Auxiliary control register (format IMPLEMENTATION DEFINED)
//0b010 Coprocessor access control register
typedef enum coprocessor_Control_registers{
	ControlRegister,
	AuxiliaryControlRegister,
	CoprocessorAccessControlRegister,
	OtherControlRegister
} CTRL_REGS;

typedef struct _cp15_reg_Controlregister{
	__u32 M:1;
	__u32 A:1;
	__u32 C:1;
	__u32 W:1;
	__u32 P:1;
	__u32 D:1;
	__u32 L:1;
	__u32 B:1;
	__u32 S:1;
	__u32 R:1;
	__u32 F:1;
	__u32 Z:1;
	__u32 I:1;
	__u32 V:1;
	__u32 RR:1;
	__u32 L4:1;
	__u32 RSVD:5;
	__u32 FI:1;
	__u32 U:1;
	__u32 XP:1;
	__u32 VE:1;
	__u32 EE:1;
	__u32 L2:1;
	__u32 c_32:4;	// should be 0000
} ControlReg;

typedef struct _cp15_reg_CoprocessorAccessRegister{
	__u32 cp0:2;
	__u32 cp1:2;
	__u32 cp2:2;
	__u32 cp3:2;
	__u32 cp4:2;
	__u32 cp5:2;
	__u32 cp6:2;
	__u32 cp7:2;
	__u32 cp8:2;
	__u32 cp9:2;
	__u32 cp10:2;
	__u32 cp11:2;
	__u32 cp12:2;
	__u32 cp13:2;
	__u32 c_32:3;	// should be 000
} CPAccessCtrlReg;
//Coprocessor access rights
//Each pair of bits corresponds to the access rights for each coprocessor:
//00 Access denied. Attempts to access corresponding coprocessor generates an undefined
//exception.
//01 Privileged access only. Attempts to access corresponding coprocessor in user mode
//generates an undefined exception.
//10 RESERVED (UNPREDICTABLE)
//11 Full access (as defined by the relevant coprocessor).
typedef enum Coprocessor_access_rights{
	AccessDenied,
	PrivilegedAccessOnly,
	RESERVED,
	FullAccess 
} CP_ACCESS_RIGHT;
//
//2 Memory protection and control Page Table 
//Control Register 2: Translation table base on page B4-41
//
//Translation table registers
typedef enum Translation_table_registers{
TTBR0,//TranslationTableBase0 0
TTBR1,//TranslationTableBase1 1
TTBR2//TranslationTableBaseControl   2
} TranslationTableRegisters;

//make TTBR0,TTBR1 the same structure
//TranslationTableBaseHi shift left to get the actual base
typedef struct TTBase{
	__u32 C:1;
	__u32 S:1;
	__u32 IMP:1;
	__u32 RGN:2;
	__u32 TranslationTableBaseHi:27;
} TTBASE;

typedef struct _TTBCtrl{
	__u32 N:3;
	__u32 UNPREDICTABLESBZ:29;
} TTBCTRL;

//3 Memory protection and control Domain Access Control 
//Register 3: Domain access control on page B4-42

//Table B4-2 Domain Access Values
//Value Access types Description
//0b00 No access Any access generates a domain fault
//0b01 Client Accesses are checked against the access permission bits in the TLB entry
//0b10 Reserved Using this value has UNPREDICTABLE results
//0b11 Manager Accesses are not checked against the access
typedef enum Domain_Access_Valuess{
	NoAccess,
	Client,
	Reserved,
	Manager 
} DomainAccessValues;


//4 Memory protection and control Reserved None. This is a reserved register.
//5 Memory protection and control Fault status Fault Address and Fault Status registers
//on page B4-19, and Register 5: Fault status on page B4-43
typedef enum Fault_Status_Registers{
CombinedDataFSR,// 0
InstructionFSR //1
}FaultStatusRegisters;


typedef struct _DFSR{
	__u32 Status:4;
	__u32 Domain:4;
	__u32 c_9:1;	// should be 0
	__u32 UNPSBZ:1;
	__u32 FS4:1;
	__u32 WR:1;
	__u32 UNPREDICTABLESBZ:20;
} DFSR;
typedef struct _IFSR{
	__u32 Status:4;
	__u32 UNPREDICTABLESBZ0:6;
	__u32 FS4:1;
	__u32 UNPREDICTABLESBZ:21;
} IFSR;


//6 Memory protection and control Fault address 
//Fault Address and Fault Status registers on page B4-19, 
//Register 6: Fault Address register on page B4-44
//Table B4-4 Fault Address registers
typedef enum Fault_Address_registers{
CombinedDataFAR,// 0
WatchpointFAR,//  1
InstructionFAR //optional
}FaultAddressRegisters;

//7 Cache and write buffer Cache/write buffer control 
//Register 7: cache management functions on page B6-19

//8 Memory protection and control TLB control 
//Register 8: TLB functions on page B4-45
                                   
//9 Cache and write buffer Cache lockdown 
//Register 9: cache lockdown functions on page B6-31

//10 Memory protection and control TLB lockdown 
//Register 10: TLB lockdown on page B4-47

//11 Tightly-coupled Memory Control DMA Control L1 DMA control using CP15 
//Register 11 on page B7-9

//12 Reserved Reserved None. This is a reserved register.
//13 Process ID Process ID 
//Register 13: Process ID on page B4-52,
//Register 13: FCSE PID on page B8-7


 typedef enum  Process_ID_registers {
FCSE_PID,// 0
CONTEXTID //1
 }  ProcessIDRegisters;

 typedef struct FCSE_ProcessID{
	__u32 UNPREDICTABLESBZ0:24;
	__u32 FCSEPid:8;
} FCSEProcessID;

typedef struct Context_ID{
	__u32 ASID:8;
	__u32 PROCID:24;
} ContextID;

//14 Reserved - -
//15 IMPLEMENTATION DEFINED 

#define CP15_DOMAINACCESS 3
#define CP15_MEMCTRL 4
#define CP15_FAULT0 5
#define CP15_FAULT1 6
#define CP15_CACHECTRL0 7
#define CP15_TLBCTRL0 8
#define CP15_CACHECTRL 9
#define CP15_TLBCTRL 10
#define CP15_CACHECTRL 9
#define CP15_TLBCTRL 10
#define CP15_TCMCTRL 11
#define CP15_REG12 12
#define CP15_PID   13
#define CP15_REG14 14
#define CP15_REG15 15


//The MMU is controlled with the System Control coprocessor registers. From VMSAv6, several new
//registers, and register fields have been added:
// a TLB type register in register 0
// additional control bits to register 1
// a second translation table base register, and new control fields to register 2
// an additional fault status register to register 5
// an additional Fault Address register to register 6
// TLB invalidate by ASID support in register 8
// ASID control in register 13.

class CMMU;

class CCP15 //: public CCP
{


	__u32 regs[16];
	//addressed by register 0:
	union
	{ 
		__u32 w[1];
		struct
		{
			MainIdReg MainIdRegister;
			CacheTypeReg CacheTypeRegister;
			TCMTypeReg TCMTypeRegister;
			MPUTypeReg  MPUTypeRegister;
			TLBTypeReg TLBTypeRegister;
		} s;
	} reg0;

	//addressed by register 1:
	union
	{ 
		__u32 w[1];
		struct
		{
			ControlReg ControlRegister;
			__u32 AuxiliaryControlRegister;
			CPAccessCtrlReg AccessRegister;
		} s;
	} reg1;

	//addressed by register 2:
	union
	{ 
		__u32 w[1];
		struct
		{
			TTBASE TTBaseReg0;
			TTBASE TTBaseReg1;
			TTBCTRL TTBaseCtrl;
		} s;
	} reg2;

	//addressed by register 5:
	union
	{ 
		__u32 w[1];
		struct
		{
			DFSR DataFSR;
			IFSR InsnFSR;
		} s;
	} reg5;
	//addressed by register 6:
	union
	{ 
		__u32 w[1];
		struct
		{
			__u32 DFAR;
			__u32 WFAR;
			__u32 IFAR;
		} s;
	} reg6;

	//addressed by register 13:
	union
	{ 
		__u32 w[1];
		struct
		{
			FCSEProcessID FCSEPid;
			ContextID ContextId;

		} s;
	} reg13;
public:
	CCP15() {reset();}

	void reset();


	MainIdReg MainIdRegister() { return reg0.s.MainIdRegister;}
	CacheTypeReg CacheTypeRegister() { return reg0.s.CacheTypeRegister;}
	TCMTypeReg TCMTypeRegister() { return reg0.s.TCMTypeRegister;}
	MPUTypeReg  MPUTypeRegister() { return reg0.s.MPUTypeRegister;}
	TLBTypeReg TLBTypeRegister() { return reg0.s.TLBTypeRegister;}
	ControlReg ControlRegister() { return reg1.s.ControlRegister;}
	__u32 AuxiliaryControlRegister() { return reg1.s.AuxiliaryControlRegister;}
	CPAccessCtrlReg AccessRegister() { return reg1.s.AccessRegister;}
	TTBASE TTBaseReg0() { return reg2.s.TTBaseReg0;}
	TTBASE TTBaseReg1() { return reg2.s.TTBaseReg1;}
	TTBCTRL TTBaseCtrl() { return reg2.s.TTBaseCtrl;}
	DFSR DataFSR() { return reg5.s.DataFSR;}
	IFSR InsnFSR() { return reg5.s.InsnFSR;}
	__u32 DFAR() { return reg6.s.DFAR;}
	__u32 WFAR() { return reg6.s.WFAR;}
	__u32 IFAR() { return reg6.s.IFAR;}
	FCSEProcessID FCSEPid() { return reg13.s.FCSEPid;}
	ContextID ContextId() { return reg13.s.ContextId;}

	void setFSR(__u8 status,bool code);
	void setFAR(__u32 address,bool code);


	friend class CMMU;
};

typedef struct _arm_insn_mcr_mrc{
        __u32 CRm:4;
        __u32 c_5:1;    // should be 1
        __u32 opcode2:3;
        __u32 c_12:4;   // should be 1111
        __u32 Rd:4;
        __u32 CRn:4;
        __u32 L:1;
        __u32 opcode1:3;
        __u32 c_28:4;   // should be 1110
        __u32 cond:4;
} ARM_INSN_MRC,ARM_INSN_MCR;
#endif //__cp15_h__